﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Cars
{
    public enum SellerType
    { 
        Unknown,
        Private,
        Dealer
    }

    public class CarInfo
    {
        public string AdId { get; set; }

        public int Year { get; set; }
        public string Make { get; set; }
        public string Model { get; set; }
        
        public decimal Price { get; set; }
        public string Description { get; set; }

        public SellerType SellerType { get; set; }
        public string ContactName { get; set; }
        public string Phone { get; set; }
        public string Cell { get; set; }

        public override string ToString()
        {
            return string.Format("{0} {1} {2} {3:C}", Year, Make, Model, Price);
        }

        // responsible to parse basic details obtained from a list view
        virtual public void ParseListView(string source)
        {
            throw new NotImplementedException();
        }

        // responsible to parse additional details obtained from a detail view
        virtual public void ParseDetailView(string source)
        {
            throw new NotImplementedException();
        }

        // CASE SENSITIVE
        // Returns the position of the character findChar.
        public static int find(string stringToSearch, int startIdx, char charToFind)
        {
            int result = -1;
            for (int i = startIdx; i < stringToSearch.Length; i++)
            {
                if (stringToSearch[i] == charToFind)
                {
                    result = i;
                    break;
                }
            }
            return result;
        }

        // CASE INSENSITIVE
        public static int find(string stringToSearch, int startIdx, string stringToFind)
        {   
            // assume this is short so just do it
            stringToFind = stringToFind.ToUpper();
            int stringToFindLength = stringToFind.Length;

            int result = -1;
            for (int i = startIdx; i < stringToSearch.Length; i++)
            {
                if (char.ToUpper(stringToSearch[i]) == stringToFind[0])
                {
                    // look ahead to see if it is actually the string
                    string tmp = copyFrom(stringToSearch, i, i + stringToFindLength);
                    if (string.Compare(copyFrom(stringToSearch,i,i+stringToFindLength), stringToFind, true) == 0)
                    {
                        result = i;
                        break;
                    }
                }
            }
            return result;
        }

        // Use this instead of string.Substring because the Substring does not
        // consider special characters such as \r and \n which ARE counted
        // by our text parsing routines
        public static string copyFrom(string source, int startIdx, int endIdx)
        {
            StringBuilder result = new StringBuilder(endIdx - startIdx);
            for (int idx = startIdx; idx < endIdx; idx++)
            {
                result.Append(source[idx]);
            }
            return result.ToString();
        }

        public static TextBlock getTextBlock(string stringToSearch, int startIdx, string stringToFind, bool returnContentsOnly)
        {
            // let's get a head start by finding the first occurrence of the openTag
            TextBlock result = new TextBlock();
            result.Text = "";
            result.StartIdx = -1;
            result.EndIdx = -1;

            int patternToFindLength = stringToFind.Length;
            
            string tagName = stringToFind.Substring(1, stringToFind.IndexOf(" ") - 1);
            string openPattern = "<" + tagName;
            int openPatternLength = openPattern.Length;
            string closePattern = "</" + tagName + ">";
            int closePatternLength = closePattern.Length;

            int i = startIdx;

            // find the opening tag
            while (i <= stringToSearch.Length - stringToFind.Length)
            {
                if (stringToSearch[i] == '<')
                {                    
                    if (string.Compare(stringToSearch.Substring(i, stringToFind.Length), stringToFind, true) == 0)
                    {
                        result.StartIdx = i;
                        // advance i to the end of this tag so we don't waste time
                        i += stringToFind.Length;
                        break;
                    }
                    // some other tag we don't care about
                    else
                    {
                        i += 1;
                    }
                }
                else
                {
                    i += 1;
                }
            }

            // we never found the opening tag, so don't continue
            if (result.StartIdx == 0)
                return result;


            //for (int i = 0; i < stringToSearch.Length; i++)
            int openCount = 0;
            while (i <= stringToSearch.Length - closePatternLength)
            {
                if (stringToSearch[i] == '<')
                {
                    // if it's another tag of the same kind (even though it's attributes may not be an exact match)
                    //  we need to increment our count so we can unwind as we find matching closing tags
                    if (string.Compare(stringToSearch.Substring(i, openPatternLength), openPattern, true) == 0)
                    {
                        openCount += 1;
                        i += openPatternLength;
                    }
                    else if (string.Compare(stringToSearch.Substring(i, closePatternLength), closePattern, true) == 0)
                    {
                        if (openCount == 0)
                        {
                            result.EndIdx = i + closePatternLength;
                            break;
                        }
                        openCount -= 1;
                        i += closePatternLength;
                    }                    
                    // some other tag we don't care about
                    else
                    {
                        i += 1;
                    }
                }
                else
                {
                    i += 1;
                }
            }

            if (result.EndIdx < result.StartIdx)
                throw new Exception(string.Format("Invalid {0} block.", stringToFind));
                        
            if ((result.EndIdx > -1) && (result.StartIdx > -1))
            {
                if (returnContentsOnly)
                {
                    result.StartIdx += stringToFind.Length;
                    result.EndIdx -= closePatternLength;
                }

                result.Text = copyFrom(stringToSearch, result.StartIdx, result.EndIdx);
                result.StartIdx = result.StartIdx;
                result.EndIdx = result.EndIdx;
            }
            
            return result;
        }
    }

}
